using System;
using System.Text;

namespace OracleInternal.I18N
{
	[Serializable]
	internal class TLBConvSJIS : TLBConv12Byte
	{
		private const short MIN_8BIT_SB = 161;

		private const short MAX_8BIT_SB = 223;

		public TLBConvSJIS()
		{
			m_groupId = 4;
		}

		protected override int GetCharsLengthImpl(byte[] bytes, int offset, int count, ref int bytesCounted)
		{
			int i = offset;
			int num = offset + count;
			if (num > bytes.Length)
			{
				num = bytes.Length;
			}
			int num2 = 0;
			for (; i < num; i++)
			{
				int num3 = bytes[i] & 0xFF;
				if (num3 > 223 || (num3 > MAX_7_8_BIT && num3 < 161))
				{
					if (i >= num - 1)
					{
						bytesCounted = i - offset;
						break;
					}
					num3 = ((bytes[i] << 8) & 0xFF00) | (bytes[i + 1] & 0xFF);
					i++;
				}
				num2 = (((ToUnicode(num3, ccb: true) & 0xFFFFFFFFu) <= 65535) ? (num2 + 1) : (num2 + 2));
			}
			bytesCounted = i - offset;
			return num2;
		}

		protected override int GetBytesOffsetImpl(byte[] bytes, int offset, int count, ref int charCount)
		{
			int i = offset;
			int num = offset + count;
			int num2 = 0;
			if (num > bytes.Length && num2 < charCount)
			{
				num = bytes.Length;
			}
			for (; i < num; i++)
			{
				if (num2 >= charCount)
				{
					break;
				}
				int num3 = bytes[i] & 0xFF;
				if (num3 > 223 || (num3 > MAX_7_8_BIT && num3 < 161))
				{
					if (i >= num - 1)
					{
						break;
					}
					num3 = ((bytes[i] << 8) & 0xFF00) | (bytes[i + 1] & 0xFF);
					i++;
				}
				num2 = (((ToUnicode(num3, ccb: true) & 0xFFFFFFFFu) <= 65535) ? (num2 + 1) : (num2 + 2));
			}
			charCount = num2;
			return i - offset;
		}

		public override int ConvertBytesToChars(byte[] bytes, int offset, int count, char[] chars, int charOffset, ref int charCount, bool ccb)
		{
			int i = offset;
			if (i < 0)
			{
				i = 0;
			}
			int num = i + count;
			if (num > bytes.Length)
			{
				num = bytes.Length;
			}
			int num2 = charOffset;
			if (num2 < 0)
			{
				num2 = 0;
			}
			int num3 = num2 + charCount;
			if (num3 > chars.Length)
			{
				num3 = chars.Length;
			}
			for (; i < num; i++)
			{
				if (num2 >= num3)
				{
					break;
				}
				int num4 = bytes[i] & 0xFF;
				if (num4 > 223 || (num4 > MAX_7_8_BIT && num4 < 161))
				{
					if (i >= num - 1)
					{
						if (ccb)
						{
							break;
						}
						throw new DecoderFallbackException("Failed to convert bytes to Unicode");
					}
					num4 = ((bytes[i] << 8) & 0xFF00) | (bytes[i + 1] & 0xFF);
					i++;
				}
				int num5 = ToUnicode(num4, ccb);
				if ((num5 & 0xFFFFFFFFu) > 65535)
				{
					if (num2 >= num3)
					{
						break;
					}
					chars[num2++] = (char)(num5 >> 16);
					chars[num2++] = (char)((uint)num5 & 0xFFFFu);
				}
				else
				{
					chars[num2++] = (char)num5;
				}
			}
			charCount = num2 - charOffset;
			return i - offset;
		}

		public override int ConvertBytesToUTF16(byte[] bytes, int offset, int count, byte[] utfbytes, int utfOffset, ref int utfCount, bool ccb)
		{
			int i = offset;
			if (i < 0)
			{
				i = 0;
			}
			int num = i + count;
			if (num > bytes.Length)
			{
				num = bytes.Length;
			}
			int num2 = utfOffset;
			if (num2 < 0)
			{
				num2 = 0;
			}
			int num3 = num2 + utfCount;
			if (num3 > utfbytes.Length)
			{
				num3 = utfbytes.Length;
			}
			for (; i < num; i++)
			{
				if (num2 + 1 >= num3)
				{
					break;
				}
				int num4 = bytes[i] & 0xFF;
				if (num4 > 223 || (num4 > MAX_7_8_BIT && num4 < 161))
				{
					if (i >= num - 1)
					{
						if (ccb)
						{
							break;
						}
						throw new DecoderFallbackException("Failed to convert bytes to Unicode");
					}
					num4 = ((bytes[i] << 8) & 0xFF00) | (bytes[i + 1] & 0xFF);
					i++;
				}
				int num5 = ToUnicode(num4, ccb);
				if ((num5 & 0xFFFFFFFFu) > 65535)
				{
					if (num2 + 3 >= num3)
					{
						break;
					}
					char[] array = new char[2]
					{
						(char)(num5 >> 16),
						(char)((uint)num5 & 0xFFFFu)
					};
					utfbytes[num2++] = (byte)(array[0] & 0xFFu);
					utfbytes[num2++] = (byte)((int)array[0] >> 8);
					utfbytes[num2++] = (byte)(array[1] & 0xFFu);
					utfbytes[num2++] = (byte)((int)array[1] >> 8);
				}
				else
				{
					utfbytes[num2++] = (byte)((uint)num5 & 0xFFu);
					utfbytes[num2++] = (byte)(num5 >> 8);
				}
			}
			utfCount = num2 - utfOffset;
			return i - offset;
		}
	}
}
